using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Web;
using System.Web.UI;
using System.ComponentModel;
using System.Reflection;

namespace CSSStyleBuilder
{
	#region Enums

	public enum Units
	{
		[Description("px")]
		px,
		[Description("pt")]
		pt,
		[Description("em")]
		em,
		[Description("ex")]
		ex,
		[Description("pc")]
		pc,
		[Description("cm")]
		cm,
		[Description("mm")]
		mm,
		[Description("in")]
		In,
		[Description("%")]
		Percent
	}

	public enum FontFamily
	{
		[Description("serif")]
		Serif,
		[Description("sans-serif")]
		SansSerif,
		[Description("cursive")]
		Cursive,
		[Description("fantasy")]
		Fantasy,
		[Description("monospace")]
		Monospace
	}

	public enum FontSize
	{
		[Description("9pt")]
		NinePoint,
		[Description("10pt")]
		TenPoint,
		[Description("12pt")]
		TwelwePoint,
		[Description("14pt")]
		FourteenPoint,
		[Description("16pt")]
		SixteenPoint,
		[Description("xx-small")]
		XXSmall,
		[Description("x-small")]
		XSmall,
		[Description("smaller")]
		Smaller,
		[Description("small")]
		Small,
		[Description("medium")]
		Medium,
		[Description("large")]
		Large,
		[Description("larger")]
		Larger,
		[Description("x-large")]
		XLarge,
		[Description("xx-large")]
		XXLarge
	}

	public enum FontWeight
	{
		[Description("normal")]
		Normal,
		[Description("bold")]
		Bold,
		[Description("bolder")]
		Bolder,
		[Description("lighter")]
		Lighter,
		[Description("100")]
		Hundred,
		[Description("200")]
		TwoHundred,
		[Description("500")]
		FiveHundred,
		[Description("600")]
		SixHundred,
		[Description("900")]
		NineHundred
	}

	public enum FontStyle
	{
		[Description("normal")]
		Normal,
		[Description("italic")]
		Italic,
		[Description("oblique")]
		Oblique
	}

	public enum FontVariant
	{
		[Description("Normal")]
		Normal,
		[Description("small-caps")]
		SmallCaps
	}

	public enum Clear
	{
		[Description("left")]
		Left,
		[Description("right")]
		Right,
		[Description("both")]
		Both,
		[Description("none")]
		None
	}

	public enum Float
	{
		[Description("Left")]
		Left,
		[Description("Right")]
		Right,
		[Description("None")]
		None
	}

	public enum TextDecoration
	{
		[Description("none")]
		None,
		[Description("underline")]
		UnderLine,
		[Description("overline")]
		OverLine,
		[Description("underline overline")]
		UnderLineOverLine,
		[Description("line-through")]
		LineThrough,
		[Description("blink")]
		Blink
	}

	public enum TextAlign
	{
		[Description("left")]
		Left,
		[Description("right")]
		Right,
		[Description("center")]
		Center,
		[Description("justify")]
		Justify
	}

	public enum TextTransform
	{
		[Description("none")]
		None,
		[Description("capitalize")]
		Capitalize,
		[Description("lowercase")]
		Lowercase,
		[Description("uppercase")]
		Uppercase
	}

	public enum VerticalAlign
	{
		[Description("baseline")]
		Baseline,
		[Description("sub")]
		Sub,
		[Description("super")]
		Super,
		[Description("top")]
		Top,
		[Description("text-top")]
		TextTop,
		[Description("middle")]
		Middle,
		[Description("bottom")]
		Bottom,
		[Description("text-bottom")]
		TextBottom
	}

	public enum BorderStyle
	{
		[Description("none")]
		None,
		[Description("solid")]
		Solid,
		[Description("double")]
		Double,
		[Description("groove")]
		Groove,
		[Description("ridge")]
		Ridge,
		[Description("inset")]
		Inset,
		[Description("outset")]
		Outset,
		[Description("dashed")]
		Dashed,
		[Description("dotted")]
		Dotted
	}

	public enum Overflow
	{
		[Description("visible")]
		Visible,
		[Description("hidden")]
		Hidden,
		[Description("scroll")]
		Scroll,
		[Description("auto")]
		Auto
	}

	public enum Display
	{
		[Description("none")]
		None,
		[Description("block")]
		Block,
		[Description("inline")]
		Inline,
		[Description("inline-block")]
		InlineBlock,
		[Description("run-in")]
		RunIn,
		[Description("compact")]
		Compact,
		[Description("list-item")]
		ListItem,
		[Description("marker")]
		Marker,
		[Description("table")]
		Table,
		[Description("table-row")]
		TableRow,
		[Description("table-cell")]
		TableCell
	}

	public enum Visibility
	{
		[Description("Visible")]
		Visible,
		[Description("Hidden")]
		Hidden
	}

	public enum Position
	{
		[Description("static")]
		Static,
		[Description("relative")]
		Relative,
		[Description("absolute")]
		Absolute,
		[Description("fixed")]
		Fixed
	}

	public enum Cursor
	{
		[Description("crosshair")]
		CrossHair,
		[Description("default")]
		Default,
		[Description("pointer")]
		Pointer,
		[Description("move")]
		Move,
		[Description("text")]
		Text,
		[Description("wait")]
		Wait,
		[Description("help")]
		Help,
		[Description("n-resize")]
		NResize,
		[Description("s-resize")]
		SResize,
		[Description("w-resize")]
		WResize,
		[Description("e-resize")]
		EResize,
		[Description("ne-resize")]
		NEResize,
		[Description("nw-resize")]
		NWResize,
		[Description("se-resize")]
		SEResize,
		[Description("sw-resize")]
		SWResize
	}

	#endregion

	public class CSSStyleOptions
	{
		#region Methods

		/// <summary>
		/// Helper function that returns the string value of the attribute on an enum value
		/// </summary>
		/// <remarks>
		/// Taken from Luke Nathan Foust's blog.  Thanks Luke!
		/// http://blog.spontaneouspublicity.com/2008/01/17/associating-strings-with-enums-in-c/
		/// </remarks>
		/// <param name="value"></param>
		/// <returns></returns>
		public static string GetEnumDescription(Enum value)
		{
			FieldInfo fi = value.GetType().GetField(value.ToString());

			DescriptionAttribute[] attributes =
				(DescriptionAttribute[])fi.GetCustomAttributes(
				typeof(DescriptionAttribute),
				false);

			if (attributes != null &&
				attributes.Length > 0)
				return attributes[0].Description;
			else
				return value.ToString();
		}

		public static IEnumerable<T> EnumToList<T>()
		{
			Type enumType = typeof(T);

			// Can't use generic type constraints on value types,
			// so have to do check like this
			if (enumType.BaseType != typeof(Enum))
				throw new ArgumentException("T must be of type System.Enum");

			Array enumValArray = Enum.GetValues(enumType);
			List<T> enumValList = new List<T>(enumValArray.Length);

			foreach (int val in enumValArray)
			{
				enumValList.Add((T)Enum.Parse(enumType, val.ToString()));
			}

			return enumValList;
		}

		public static string GetEnumDescription<T>(T member)
		{
			FieldInfo fi = typeof(T).GetField(member.ToString());

			DescriptionAttribute[] attributes =
				(DescriptionAttribute[])fi.GetCustomAttributes(
				typeof(DescriptionAttribute),
				false);

			if (attributes != null &&
				attributes.Length > 0)
				return attributes[0].Description;
			else
				return typeof(T).ToString();
		}

		public static List<string> GetEnumDescriptionList<T>()
		{
			Type enumType = typeof(T);

			// Can't use generic type constraints on value types,
			// so have to do check like this
			if (enumType.BaseType != typeof(Enum))
				throw new ArgumentException("T must be of type System.Enum");

			IEnumerable<T> list = EnumToList<T>();
			List<string> listOfDescriptions = new List<string>();
			foreach (T listMember in list)
			{
				listOfDescriptions.Add(GetEnumDescription<T>(listMember));
			}

			return listOfDescriptions;
		}

		private System.Web.UI.WebControls.TextBox m_dummyControl;

		private CssStyleCollection m_styleCollection;

		public CssStyleCollection StyleCollection
		{
			get { return m_styleCollection; }
			set { m_styleCollection = value; }
		}

		private void RemoveKey(CssStyleCollection StyleCollection, string key)
		{
			while (StyleCollection[key] != null)
			{
				try
				{
					HtmlTextWriterStyle htws = (HtmlTextWriterStyle)Enum.Parse(typeof(HtmlTextWriterStyle), key.Replace("-", ""), true);
					StyleCollection.Remove(htws);
				}
				catch (System.ArgumentException)
				{
					StyleCollection.Remove(key);
				}
			}
		}

		private void RemoveKey(CssStyleCollection StyleCollection, HtmlTextWriterStyle key)
		{
			while (StyleCollection[key] != null)
			{
				StyleCollection.Remove(key);
			}
		}

		public CSSStyleOptions()
		{
			m_dummyControl = new System.Web.UI.WebControls.TextBox();
			m_styleCollection = m_dummyControl.Style;
		}

		#endregion

		#region Properties

		#region Color related members

		public string Color
		{
			get { return StyleCollection[HtmlTextWriterStyle.Color]; }
			set
			{
				if (StyleCollection[HtmlTextWriterStyle.Color] != null)
				{
					RemoveKey(StyleCollection, HtmlTextWriterStyle.Color);
				}
				StyleCollection.Add(HtmlTextWriterStyle.Color, value);
			}
		}

		public string BackgroundColor
		{
			get { return StyleCollection[HtmlTextWriterStyle.BackgroundColor]; }
			set
			{
				if (StyleCollection[HtmlTextWriterStyle.BackgroundColor] != null)
				{
					RemoveKey(StyleCollection, HtmlTextWriterStyle.BackgroundColor);
				}
				StyleCollection.Add(HtmlTextWriterStyle.BackgroundColor, value);
			}
		}

		#endregion

		#region Font related members

		public string LineHeight
		{
			get { return ((StyleCollection["line-height"] == null) ? string.Empty : StyleCollection["line-height"]); }
			set
			{
				if (StyleCollection["line-height"] != null)
				{
					RemoveKey(StyleCollection, "line-height");
				}
				StyleCollection.Add("line-height", value);
			}
		}

		#endregion

		#region Border related members

		public string BorderWidth
		{
			get { return ((StyleCollection["border-width"] == null) ? string.Empty : StyleCollection["border-width"]); }
			set
			{
				if (StyleCollection["border-width"] != null)
				{
					RemoveKey(StyleCollection, "border-width");
				}
				StyleCollection.Add("border-width", value);
			}
		}

		public string BorderTopWidth
		{
			get
			{
				return (StyleCollection["border-top-width"] == null) ? string.Empty : StyleCollection["border-top-width"];
			}
			set
			{

				if (StyleCollection["border-top-width"] != null)
				{
					RemoveKey(StyleCollection, "border-top-width");
				}
				StyleCollection.Add("border-top-width", value);
			}
		}

		public string BorderLeftWidth
		{
			get
			{
				return (StyleCollection["border-left-width"] == null) ? string.Empty : StyleCollection["border-left-width"];
			}
			set
			{

				if (StyleCollection["border-left-width"] != null)
				{
					RemoveKey(StyleCollection, "border-left-width");
				}
				StyleCollection.Add("border-left-width", value);
			}
		}

		public string BorderRightWidth
		{
			get
			{
				return (StyleCollection["border-right-width"] == null) ? string.Empty : StyleCollection["border-right-width"];
			}
			set
			{

				if (StyleCollection["border-right-width"] != null)
				{
					RemoveKey(StyleCollection, "border-right-width");
				}
				StyleCollection.Add("border-right-width", value);
			}
		}

		public string BorderBottomWidth
		{
			get
			{
				return (StyleCollection["border-bottom-width"] == null) ? string.Empty : StyleCollection["border-bottom-width"];
			}
			set
			{

				if (StyleCollection["border-bottom-width"] != null)
				{
					RemoveKey(StyleCollection, "border-bottom-width");
				}
				StyleCollection.Add("border-bottom-width", value);
			}
		}

		public string BorderColor
		{
			get { return (StyleCollection["border-color"] == null) ? string.Empty : StyleCollection["border-color"]; }
			set
			{
				if (StyleCollection["border-color"] != null)
				{
					RemoveKey(StyleCollection, "border-color");
				}
				StyleCollection.Add("border-color", value);
			}
		}

		public string BorderTopColor
		{
			get
			{
				return (StyleCollection["border-top-color"] == null) ? string.Empty : StyleCollection["border-top-color"];
			}
			set
			{

				if (StyleCollection["border-top-color"] != null)
				{
					RemoveKey(StyleCollection, "border-top-color");
				}
				StyleCollection.Add("border-top-color", value);
			}
		}

		public string BorderLeftColor
		{
			get
			{
				return (StyleCollection["border-left-color"] == null) ? string.Empty : StyleCollection["border-left-color"];
			}
			set
			{

				if (StyleCollection["border-left-color"] != null)
				{
					RemoveKey(StyleCollection, "border-left-color");
				}
				StyleCollection.Add("border-left-color", value);
			}
		}

		public string BorderRightColor
		{
			get
			{
				return (StyleCollection["border-right-color"] == null) ? string.Empty : StyleCollection["border-right-color"];
			}
			set
			{

				if (StyleCollection["border-right-color"] != null)
				{
					RemoveKey(StyleCollection, "border-right-color");
				}
				StyleCollection.Add("border-right-color", value);
			}
		}

		public string BorderBottomColor
		{
			get
			{
				return (StyleCollection["border-bottom-color"] == null) ? string.Empty : StyleCollection["border-bottom-color"];
			}
			set
			{

				if (StyleCollection["border-bottom-color"] != null)
				{
					RemoveKey(StyleCollection, "border-bottom-color");
				}
				StyleCollection.Add("border-bottom-color", value);
			}
		}

		public string BorderStyle
		{
			get { return ((StyleCollection["border-style"] == null) ? string.Empty : StyleCollection["border-style"]); }
			set
			{

				if (StyleCollection["border-style"] != null)
				{
					RemoveKey(StyleCollection, "border-style");
				}
				StyleCollection.Add("border-style", value);
			}
		}

		public string BorderTopStyle
		{
			get
			{
				return (StyleCollection["border-top-style"] == null) ? string.Empty : StyleCollection["border-top-style"];
			}
			set
			{

				if (StyleCollection["border-top-style"] != null)
				{
					RemoveKey(StyleCollection, "border-top-style");
				}
				StyleCollection.Add("border-top-style", value);
			}
		}

		public string BorderLeftStyle
		{
			get
			{
				return (StyleCollection["border-left-style"] == null) ? string.Empty : StyleCollection["border-left-style"];
			}
			set
			{

				if (StyleCollection["border-left-style"] != null)
				{
					RemoveKey(StyleCollection, "border-left-style");
				}
				StyleCollection.Add("border-left-style", value);
			}
		}

		public string BorderRightStyle
		{
			get
			{
				return (StyleCollection["border-right-style"] == null) ? string.Empty : StyleCollection["border-right-style"];
			}
			set
			{

				if (StyleCollection["border-right-style"] != null)
				{
					RemoveKey(StyleCollection, "border-right-style");
				}
				StyleCollection.Add("border-right-style", value);
			}
		}

		public string BorderBottomStyle
		{
			get
			{
				return (StyleCollection["border-bottom-style"] == null) ? string.Empty : StyleCollection["border-bottom-style"];
			}
			set
			{

				if (StyleCollection["border-bottom-style"] != null)
				{
					RemoveKey(StyleCollection, "border-bottom-style");
				}
				StyleCollection.Add("border-bottom-style", value);
			}
		}

		#endregion

		#region Padding and Margin related members

		public string Padding
		{
			get { return ((StyleCollection["padding"] == null) ? string.Empty : StyleCollection["padding"]); }
			set
			{
				if (StyleCollection["padding"] != null)
				{
					RemoveKey(StyleCollection, "padding");
				}
				StyleCollection.Add("padding", value);
			}
		}

		public string PaddingTop
		{
			get
			{
				return (StyleCollection["padding-top"] == null) ? string.Empty : StyleCollection["padding-top"];
			}
			set
			{

				if (StyleCollection["padding-top"] != null)
				{
					RemoveKey(StyleCollection, "padding-top");
				}
				StyleCollection.Add("padding-top", value);
			}
		}

		public string PaddingLeft
		{
			get
			{
				return (StyleCollection["padding-left"] == null) ? string.Empty : StyleCollection["padding-left"];
			}
			set
			{

				if (StyleCollection["padding-left"] != null)
				{
					RemoveKey(StyleCollection, "padding-left");
				}
				StyleCollection.Add("padding-left", value);
			}
		}

		public string PaddingRight
		{
			get
			{
				return (StyleCollection["padding-right"] == null) ? string.Empty : StyleCollection["padding-right"];
			}
			set
			{

				if (StyleCollection["padding-right"] != null)
				{
					RemoveKey(StyleCollection, "padding-right");
				}
				StyleCollection.Add("padding-right", value);
			}
		}

		public string PaddingBottom
		{
			get
			{
				return (StyleCollection["padding-bottom"] == null) ? string.Empty : StyleCollection["padding-bottom"];
			}
			set
			{

				if (StyleCollection["padding-bottom"] != null)
				{
					RemoveKey(StyleCollection, "padding-bottom");
				}
				StyleCollection.Add("padding-bottom", value);
			}
		}

		public string Margin
		{
			get { return ((StyleCollection["margin"] == null) ? string.Empty : StyleCollection["margin"]); }
			set
			{
				if (StyleCollection["margin"] != null)
				{
					RemoveKey(StyleCollection, "margin");
				}
				StyleCollection.Add("margin", value);
			}
		}

		public string MarginTop
		{
			get
			{
				return (StyleCollection["margin-top"] == null) ? string.Empty : StyleCollection["margin-top"];
			}
			set
			{

				if (StyleCollection["margin-top"] != null)
				{
					RemoveKey(StyleCollection, "margin-top");
				}
				StyleCollection.Add("margin-top", value);
			}
		}

		public string MarginLeft
		{
			get
			{
				return (StyleCollection["margin-left"] == null) ? string.Empty : StyleCollection["margin-left"];
			}
			set
			{

				if (StyleCollection["margin-left"] != null)
				{
					RemoveKey(StyleCollection, "margin-left");
				}
				StyleCollection.Add("margin-left", value);
			}
		}

		public string MarginRight
		{
			get
			{
				return (StyleCollection["margin-right"] == null) ? string.Empty : StyleCollection["margin-right"];
			}
			set
			{

				if (StyleCollection["margin-right"] != null)
				{
					RemoveKey(StyleCollection, "margin-right");
				}
				StyleCollection.Add("margin-right", value);
			}
		}

		public string MarginBottom
		{
			get
			{
				return (StyleCollection["margin-bottom"] == null) ? string.Empty : StyleCollection["margin-bottom"];
			}
			set
			{

				if (StyleCollection["margin-bottom"] != null)
				{
					RemoveKey(StyleCollection, "margin-bottom");
				}
				StyleCollection.Add("margin-bottom", value);
			}
		}

		#endregion

		#region Div related members

		public string Float
		{
			get { return (StyleCollection["float"] == null) ? string.Empty : StyleCollection["float"]; }
			set
			{
				if (StyleCollection["float"] != null)
				{
					RemoveKey(StyleCollection, "float");
				}
				StyleCollection.Add("float", value);
			}
		}

		public string Clear
		{
			get { return (StyleCollection["clear"] == null) ? string.Empty : StyleCollection["clear"]; }
			set
			{
				if (StyleCollection["clear"] != null)
				{
					RemoveKey(StyleCollection, "clear");
				}
				StyleCollection.Add("clear", value);
			}
		}

		public string TextIndent
		{
			get { return ((StyleCollection["text-indent"] == null) ? string.Empty : StyleCollection["text-indent"]); }
			set
			{
				if (StyleCollection["text-indent"] != null)
				{
					RemoveKey(StyleCollection, "text-indent");
				}
				StyleCollection.Add("text-indent", value);
			}
		}

		public string LetterSpacing
		{
			get { return ((StyleCollection["letter-spacing"] == null) ? string.Empty : StyleCollection["letter-spacing"]); }
			set
			{
				if (StyleCollection["letter-spacing"] != null)
				{
					RemoveKey(StyleCollection, "letter-spacing");
				}
				StyleCollection.Add("letter-spacing", value);
			}
		}

		public string WordSpacing
		{
			get { return (StyleCollection["word-spacing"] == null) ? string.Empty : StyleCollection["word-spacing"]; }
			set
			{
				if (StyleCollection["word-spacing"] != null)
				{
					RemoveKey(StyleCollection, "word-spacing");
				}
				StyleCollection.Add("word-spacing", value);
			}
		}

		public string TextTransform
		{
			get { return (StyleCollection["text-transform"] == null) ? string.Empty : StyleCollection["text-transform"]; }
			set
			{
				if (StyleCollection["text-transform"] != null)
				{
					RemoveKey(StyleCollection, "text-transform");
				}
				StyleCollection.Add("text-transform", value);
			}
		}

		#endregion

		#region Postioning related members

		public string Right
		{
			get { return (StyleCollection["right"] == null) ? string.Empty : StyleCollection["right"]; }
			set
			{
				if (StyleCollection["right"] != null)
				{
					RemoveKey(StyleCollection, "right");
				}
				StyleCollection.Add("right", value);
			}
		}

		public string Bottom
		{
			get { return (StyleCollection["bottom"] == null) ? string.Empty : StyleCollection["bottom"]; }
			set
			{
				if (StyleCollection["bottom"] != null)
				{
					RemoveKey(StyleCollection, "bottom");
				}
				StyleCollection.Add("bottom", value);
			}
		}

		#endregion

		#endregion
	}
}
